<template>
  <view class="waterfall">
    <view v-for="(item, index) of columnData" :key="index" class="column" :style="{ width: `${columnWidth}px` }">
      <view v-for="(childItem, childIndex) in item" :id="`item${childItem.id}`" :key="childIndex"
            class="w-full" @click.stop="click(childItem)">
        <slot :item="childItem">
          <view class="item" style="`background-color:#fff;margin:10rpx;border-radius:8rpx;`">
            <image :src="childItem.picUrl" mode="widthFix" lazy-load
                   :style="{ height: childItem.height, width: '100%' }" />
            <view class="title-info">
              <view class="item-title">{{ childItem.title }}</view>
              <view class="item-desc">{{ childItem.desc }}</view>
            </view>
          </view>
        </slot>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, watch, nextTick } from 'vue'

const props = defineProps({
  dataList: { type: Array, required: true, default: () => [] },
  //显示列数
  column: { type: Number, required: true, default: 2 },
})
const emit = defineEmits(['click'])

let columnData = ref([])
let columnWidth = ref(0)

watch(() => props.dataList, () => {
  nextTick(() => {
    setColumnWidth()
    setData()
  })
}, { immediate: true, deep: true })

watch(() => props.column, () => {
  nextTick(() => {
    setColumnWidth()
    setData()
  })
}, { immediate: true, deep: true })

//计算每列的高度
const  getElemHeight = () => {
  nextTick(() => {
    let arr = []
    props.dataList.forEach(item => {
      uni.getImageInfo({
        src: item.picUrl,
        success: (e) => {
          item.height = `${e.height * (columnWidth.value / e.width)}px`
          uni.createSelectorQuery()
            .select(`#item${item.id}`)
            .boundingClientRect(res => {
              arr.push({
                itemHeight: res.height,
                ...item,
              })
              if (arr.length === props.dataList.length) {
                columnData.value = distributeToNArrays(arr, props.column)
              }
            }).exec()
        },
      })
    })
  })
}
const  distributeToNArrays = (arr, n) => {
  let sums = new Array(n).fill(0)
  return arr.reduce(
    (arrays, item) => {
      let minSum = Math.min(...sums)
      let minIndex = sums.indexOf(minSum)
      arrays[minIndex].push(item)
      sums[minIndex] += item.itemHeight
      return arrays
    },
    new Array(n).fill().map(() => []),
  )
}
const setColumnWidth = () => {
  let width = uni.getSystemInfoSync().windowWidth
  columnWidth.value = Math.floor(width / props.column)
}
const setData = () => {
  const resultArray = props.dataList.reduce(
    (acc, cur, index) => {
      const targetIndex = index % props.column
      acc[targetIndex].push(cur)
      return acc
    },
    Array.from(Array(props.column), () => []),
  )
  columnData.value = resultArray
  getElemHeight()
}
const click = (item) => {
  emit('click', item)
}
</script>

<style lang="scss" scoped>
.waterfall {
  display: flex;
  flex-flow: row wrap;

  .column {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .item {
    overflow: hidden;
  }

  .title-info {
    padding: 0rpx 20rpx 20rpx;
  }

  .item-title {
    font-size: 30rpx;
    color: #333;
    line-height: 46rpx;
    text-align: justify;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
  }

  .item-desc {
    margin-top: 4rpx;
    font-size: 26rpx;
    color: #666;
    line-height: 34rpx;
    text-align: justify;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
  }
}
</style>
